package com.cskaoyan.javase.recursion._0introduction;

/**
 * 我们已经学习过方法，使用过方法了。方法体中是可以调用方法的，那么如果在方法体中调用方法自身呢？
 *
 * 特别的，在一个方法当中再次调用这个方法，就像故事里提到同样的故事一样，我们把方法在运行时调用自身的情况，称之为递归，又叫做递归调用。
 *
 *
 * 使用的递归的注意事项:
 *      1.首先需要找到方法体中,自身调用自身的代码
 *      这称之为递归体
 *      没有递归体肯定不是递归
 *
 *      2.光有递归体的递归肯定是不行的,方法只进栈不出栈一定会栈溢出,所以需要给出一个条件让方法结束调用出栈,这称之为"递归的出口"
 *      对于一个正常的递归而言,递归的出口必不可少
 *
 *      3.思考: 一个有递归的出口就一定不会出错吗?一定不会栈溢出?一定安全吗?
 *      不一定,递归即便有出口,也需要考虑递归的次数
 *      称之为"递归的深度"
 *      递归的深度不能超过栈的空间大小
 *      否者仍然会栈溢出
 *
 * 总之: 递归是很危险的,使用递归之前一定要严格考虑递归的出口和递归的深度.递归虽然很好,但是能不用尽量不用
 *
 *
 * @since 17:34
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        System.out.println(sum(20000));
        /*
            分析一下这个方法调用
            sum(10) = 10 + sum(9);
            sum(9) = 9 + sum(8);
            sum(8) = 8 + sum(7);
            .....
            很明显这个过程不可能自己停下来,会无限的去调用方法
            那么思考程序的结果是什么?
                1.死循环
                2.程序运行出错
                3.电脑炸了 (不是)
           运行发现,程序运行报错,抛出异常StackOverflowError,然后程序终止执行
           StackOverflowError: 栈溢出错误
           Error也是一种异常,但是它比Exception更加严重,它是错误

           为什么会栈溢出?这个栈溢出是什么栈溢出了?
           是JVM栈,栈空间不足,就会报栈溢出错误

           写了递归出口后,再来分析这个程序
           if (num == 0) {
                return 0;
            }
           sum(10) = 10 + sum(9);
           sum(9) = 9 + sum(8);
           ....
           sum(1) = 1 + sum(0)
           sum(0) = 0
           sum(10) = 55
         */
    }

    // 以下就是一个递归方法
    // Method 'sum()' recurses infinitely, and can only end by throwing an exception
    public static int sum(int num) {
        // 递归需要出口,否则一定栈溢出
        if (num == 0) {
            return 0;
        }
        return num + sum(num - 1);
    }
}
